#ifndef RTTHREADMANAGER_H
#define RTTHREADMANAGER_H


#include "RtDefines.h"
#include "RtMutex.h"
#include <vector>

class CRtTimeValue;
class CRtThread;
class IRtReactor;
class IRtEventQueue;
class IRtTimerQueue;

class RT_API_EXPORT CRtThreadManager  
{
public:
	CRtThreadManager();
	~CRtThreadManager();
	
	static CRtThreadManager* Instance();
	static void CleanupOnlyOne();

	RtResult InitMainThread(int aArgc, char** aArgv);
	
	typedef int TType;
	enum 
	{
		TT_MAIN,
		TT_NETWORK,
		TT_DNS,
		TT_CURRENT,
		TT_TIMER,
		TT_UNKNOWN = -1,
		
		// This private thread type is used by applications. 
		TT_USER_DEFINE_BASE = 1000
	};

	enum TFlag
	{
		TF_NONE = 0,
		TF_JOINABLE = (1 << 0),
		TF_DETACHED = (1 << 1)
	};

	CRtThread* GetThread(TType aType);
	IRtReactor* GetThreadReactor(TType aType);
	IRtEventQueue* GetThreadEventQueue(TType aType);
	IRtTimerQueue* GetThreadTimerQueue(TType aType);

	// create Reactor Thread (mainly for network)
//	RtResult CreateUserReactorThread(CRtThread *&aThread);

	// create Task Thread (include EventQueue and TimerQueue only)
	RtResult CreateUserTaskThread(
		CRtThread *&aThread, 
		TFlag aFlag = TF_JOINABLE,
		BOOL bWithTimerQueue = TRUE);

	// get user thread type (TT_USER_DEFINE_BASE + x)
	TType GetAndIncreamUserType();

	static void SleepMs(DWORD aMsec);

public:
	// the following member functions are mainly used in TP.
	RtResult CreateReactorThread(TType aType, IRtReactor *aReactor, CRtThread *&aThread);
	
	// mainly invoked by CRtThreadManager::~CRtThreadManager()
	RtResult StopAllThreads(CRtTimeValue* aTimeout = NULL);
	RtResult JoinAllThreads();

	// mainly invoked by CRtThread::Create().
	RtResult RegisterThread(CRtThread* aThread);

	RtResult UnregisterThread(CRtThread* aThread);

	void GetSingletonMutex(CRtMutexThreadRecursive *&aMutex);
//	{
//		aMutex = &m_SingletonMutex;
//	}

	void GetReferenceControlMutex(CRtMutexThread *&aMutex)
	{
		aMutex = &m_ReferenceControlMutexThread;
	}

	// thread module
	enum TModule
	{
		TM_SINGLE_MAIN,
		TM_MULTI_ONE_DEDICATED,
		TM_MULTI_POOL
	};
	static TModule GetNetworkThreadModule();
	
	static RT_THREAD_ID GetThreadSelfId()
	{
#ifdef WIN32
		return ::GetCurrentThreadId();
#else
		return ::pthread_self();
#endif // WIN32
	}
	
	static BOOL IsThreadEqual(RT_THREAD_ID aT1, RT_THREAD_ID aT2)
	{
#ifdef WIN32
		return aT1 == aT2;
#else
	#if defined (MACOS) && !defined(MachOSupport)
		return CFM_pthread_equal(aT1, aT2);
	#else
		return ::pthread_equal(aT1, aT2);
	#endif	
#endif // WIN32
	}

	static BOOL IsEqualCurrentThread(RT_THREAD_ID aId)
	{
		return IsThreadEqual(aId, GetThreadSelfId());
	}

	static BOOL IsEqualCurrentThread(TType aType);

	// mainly for init winsock2
	static RtResult SocketStartup();
	static RtResult SocketCleanup();

	static IRtReactor* CreateNetworkReactor();

private:
	RtResult SpawnNetworkThread_i();

private:
#ifdef RT_WIN32
	static BOOL s_bSocketInited;
#endif // RT_WIN32
	
	// singleton mutex is recursive due to CRtCleanUpBase() will lock it too.
	CRtMutexThreadRecursive m_SingletonMutex;
	CRtMutexThread m_ReferenceControlMutexThread;

	typedef std::vector<CRtThread *> ThreadsType;
	ThreadsType m_Threads;
	typedef CRtMutexThread MutexType ;
	MutexType m_Mutex;
	TType m_TTpyeUserThread;
	
	/**Added by Webb**/
	CRtThread *m_pThreadNetwork;

private:
	// = Prevent assignment and initialization.
	void operator = (const CRtThreadManager&);
	CRtThreadManager(const CRtThreadManager&);
};

#endif // !RTTHREADMANAGER_H
